/*
 * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "OutdoorPvPSI.h"
#include "WorldPacket.h"
#include "Player.h"
#include "GameObject.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
#include "Language.h"
#include "World.h"
#include "ScriptPCH.h"

OutdoorPvPSI::OutdoorPvPSI() {
	m_TypeId = OUTDOOR_PVP_SI;
	m_Gathered_A = 0;
	m_Gathered_H = 0;
	m_LastController = 0;
}

void OutdoorPvPSI::FillInitialWorldStates(WorldPacket &data) {
	data << SI_GATHERED_A << m_Gathered_A;
	data << SI_GATHERED_H << m_Gathered_H;
	data << SI_SILITHYST_MAX << SI_MAX_RESOURCES;
}

void OutdoorPvPSI::SendRemoveWorldStates(Player *plr) {
	plr->SendUpdateWorldState(SI_GATHERED_A, 0);
	plr->SendUpdateWorldState(SI_GATHERED_H, 0);
	plr->SendUpdateWorldState(SI_SILITHYST_MAX, 0);
}

void OutdoorPvPSI::UpdateWorldState() {
	SendUpdateWorldState(SI_GATHERED_A, m_Gathered_A);
	SendUpdateWorldState(SI_GATHERED_H, m_Gathered_H);
	SendUpdateWorldState(SI_SILITHYST_MAX, SI_MAX_RESOURCES);
}

bool OutdoorPvPSI::SetupOutdoorPvP() {
	for (uint8 i = 0; i < OutdoorPvPSIBuffZonesNum; ++i)
		RegisterZone(OutdoorPvPSIBuffZones[i]);
	return true;
}

bool OutdoorPvPSI::Update(uint32 /*diff*/) {
	return false;
}

void OutdoorPvPSI::HandlePlayerEnterZone(Player * plr, uint32 zone) {
	if (plr->GetTeam() == m_LastController)
		plr->CastSpell(plr, SI_CENARION_FAVOR, true);
	OutdoorPvP::HandlePlayerEnterZone(plr, zone);
}

void OutdoorPvPSI::HandlePlayerLeaveZone(Player * plr, uint32 zone) {
	// remove buffs
	plr->RemoveAurasDueToSpell(SI_CENARION_FAVOR);
	OutdoorPvP::HandlePlayerLeaveZone(plr, zone);
}

bool OutdoorPvPSI::HandleAreaTrigger(Player *plr, uint32 trigger) {
	switch (trigger) {
	case SI_AREATRIGGER_A:
		if (plr->GetTeam() == ALLIANCE && plr->HasAura(SI_SILITHYST_FLAG)) {
			// remove aura
			plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG);
			++m_Gathered_A;
			if (m_Gathered_A >= SI_MAX_RESOURCES) {
				TeamApplyBuff(TEAM_ALLIANCE, SI_CENARION_FAVOR);
				sWorld->SendZoneText(
						OutdoorPvPSIBuffZones[0],
						sObjectMgr->GetArkCoreStringForDBCLocale(
								LANG_OPVP_SI_CAPTURE_A));
				m_LastController = ALLIANCE;
				m_Gathered_A = 0;
				m_Gathered_H = 0;
			}
			UpdateWorldState();
			// reward player
			plr->CastSpell(plr, SI_TRACES_OF_SILITHYST, true);
			// add 19 honor
			plr->RewardHonor(NULL, 1, 19);
			// add 20 cenarion circle repu
			plr->GetReputationMgr().ModifyReputation(
					sFactionStore.LookupEntry(609), 20);
			// complete quest
			plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_A, 0);
		}
		return true;
	case SI_AREATRIGGER_H:
		if (plr->GetTeam() == HORDE && plr->HasAura(SI_SILITHYST_FLAG)) {
			// remove aura
			plr->RemoveAurasDueToSpell(SI_SILITHYST_FLAG);
			++m_Gathered_H;
			if (m_Gathered_H >= SI_MAX_RESOURCES) {
				TeamApplyBuff(TEAM_HORDE, SI_CENARION_FAVOR);
				sWorld->SendZoneText(
						OutdoorPvPSIBuffZones[0],
						sObjectMgr->GetArkCoreStringForDBCLocale(
								LANG_OPVP_SI_CAPTURE_H));
				m_LastController = HORDE;
				m_Gathered_A = 0;
				m_Gathered_H = 0;
			}
			UpdateWorldState();
			// reward player
			plr->CastSpell(plr, SI_TRACES_OF_SILITHYST, true);
			// add 19 honor
			plr->RewardHonor(NULL, 1, 19);
			// add 20 cenarion circle repu
			plr->GetReputationMgr().ModifyReputation(
					sFactionStore.LookupEntry(609), 20);
			// complete quest
			plr->KilledMonsterCredit(SI_TURNIN_QUEST_CM_H, 0);
		}
		return true;
	}
	return false;
}

bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId) {
	if (spellId == SI_SILITHYST_FLAG) {
		// if it was dropped away from the player's turn-in point, then create a silithyst mound, if it was dropped near the areatrigger, then it was dispelled by the outdoorpvp, so do nothing
		switch (plr->GetTeam()) {
		case ALLIANCE: {
			AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(
					SI_AREATRIGGER_A);
			if (atEntry) {
				// 5.0f is safe-distance
				if (plr->GetDistance(atEntry->x, atEntry->y, atEntry->z)
						> 5.0f + atEntry->radius) {
					// he dropped it further, summon mound
					GameObject * go = new GameObject;
					Map * map = plr->GetMap();
					if (!map) {
						delete go;
						return true;
					}

					if (!go->Create(
							sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), SI_SILITHYST_MOUND, map, plr->GetPhaseMask(), plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY))
							{
								delete go;
							}
							else
							{
								go->SetRespawnTime(0);
								map->Add(go);
							}
						}
					}
				}
				break;
				case HORDE:
				{
					AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(SI_AREATRIGGER_H);
					if (atEntry)
					{
						// 5.0f is safe-distance
						if (plr->GetDistance(atEntry->x, atEntry->y, atEntry->z) > 5.0f + atEntry->radius)
						{
							// he dropped it further, summon mound
							GameObject * go = new GameObject;
							Map * map = plr->GetMap();
							if (!map)
							{
								delete go;
								return true;
							}
							if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), SI_SILITHYST_MOUND, map, plr->GetPhaseMask() , plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY))
							{
								delete go;
							}
							else
							{
								go->SetRespawnTime(0);
								map->Add(go);
							}
						}
					}
				}
				break;
			}
			return true;
		}
		return false;
	}

bool OutdoorPvPSI::HandleCustomSpell(Player *plr, uint32 spellId,
		GameObject *go) {
	if (!go || spellId != SI_SILITHYST_FLAG_GO_SPELL)
		return false;
	plr->CastSpell(plr, SI_SILITHYST_FLAG, true);
	if (go->GetGOInfo()->id == SI_SILITHYST_MOUND) {
		// despawn go
		go->SetRespawnTime(0);
		go->Delete();
	}
	return true;
}

class OutdoorPvP_silithus: public OutdoorPvPScript {
public:

	OutdoorPvP_silithus() :
			OutdoorPvPScript("outdoorpvp_si") {
	}

	OutdoorPvP* GetOutdoorPvP() const {
		return new OutdoorPvPSI();
	}
};

void AddSC_outdoorpvp_si() {
	new OutdoorPvP_silithus();
}
